//  This file is part of Swordbible - http://www.swordwarrior.net
//  Copyright (C) 2003-2009 Manu Mital mital.manu@gmail.com

//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2, or (at your option)
//  any later version.

//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.

//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


// NotesPage.cpp : implementation file
//


#include <stdafx.h>
#include "SwordBible.h"
#include  <AfxPriv.h>
#include "SwordBibleDoc.h"
#include ".\notespage.h"
#include "NotesPage.h"
#include "BibleForm.h"
#include <odbcinst.h> 
#include <afxdb.h> 
#include "VersePicker.h"
#include "MainFrm.h"

// CNotesPage dialog

CString CNotesPage::ActiveMainFrameCommand = _T("");
CString CNotesPage::path;

IMPLEMENT_DYNAMIC(CNotesPage, CPropertyPage)
CNotesPage::CNotesPage()
	: CPropertyPage(CNotesPage::IDD)
{
}

CNotesPage::~CNotesPage()
{
}

void CNotesPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_RICHEDIT_NOTES, m_notesCtrl);
	DDX_Control(pDX, IDC_COMBO_NOTES_BOOK, m_cmbBibleBook);
	DDX_Control(pDX, IDC_COMBO_NOTES_CHAPTER, m_cmbBibleChapter);
	DDX_Control(pDX, IDC_FONTNAME, m_cmbFontName);
	DDX_Control(pDX, IDC_FONTSIZE, m_cmbFontSize);
}


BEGIN_MESSAGE_MAP(CNotesPage, CPropertyPage)
	ON_WM_SIZE()
	ON_COMMAND(ID_CHAR_COLOR, OnCharColor)
	ON_COMMAND(ID_CHAR_ITALIC, OnCharItalic)
	ON_UPDATE_COMMAND_UI(ID_CHAR_ITALIC, OnUpdateCharItalic)
	ON_COMMAND(ID_CHAR_UNDERLINE, OnCharUnderline)
	ON_UPDATE_COMMAND_UI(ID_CHAR_UNDERLINE, OnUpdateCharUnderline)
	ON_COMMAND(ID_INSERT_BULLET, OnInsertBullet)
	ON_UPDATE_COMMAND_UI(ID_INSERT_BULLET, OnUpdateInsertBullet)
	ON_COMMAND(ID_PARA_CENTER, OnParaCenter)
	ON_UPDATE_COMMAND_UI(ID_PARA_CENTER, OnUpdateParaCenter)
	ON_COMMAND(ID_PARA_LEFT, OnParaLeft)
	ON_UPDATE_COMMAND_UI(ID_PARA_LEFT, OnUpdateParaLeft)
	ON_COMMAND(ID_PARA_RIGHT, OnParaRight)
	ON_UPDATE_COMMAND_UI(ID_PARA_RIGHT, OnUpdateParaRight)
	ON_COMMAND(ID_CHAR_BOLD, OnCharBold)
	ON_UPDATE_COMMAND_UI(ID_CHAR_BOLD, OnUpdateCharBold)
	ON_COMMAND(ID_RTF_COPY, OnRtfCopy)
	ON_COMMAND(ID_RTF_CUT, OnRtfCut)
	ON_COMMAND(ID_RTF_PASTE, OnRtfPaste)
	ON_COMMAND(ID_RTF_SAVE, OnRtfSave)
	ON_COMMAND(ID_SYNCH, OnSynch)
	ON_UPDATE_COMMAND_UI(ID_SYNCH, OnUpdateSynch)
	ON_COMMAND(ID_NOTES_PRINT, OnNotesPrint)
  ON_COMMAND(ID_NOTES_INSERTLINK, OnInsertLink)
	ON_WM_DESTROY()

	ON_MESSAGE(NM_RETURN,OnBarReturn)
	ON_MESSAGE(ID_NOTES_COMMAND,OnMainFrameCommand)


	ON_MESSAGE(FN_BIBLECHAP_NOTES, OnChangeNotesChapter)
	ON_MESSAGE(FN_BIBLEBOOK_NOTES, OnChangeNotesBook)
	
	 ON_NOTIFY(EN_MSGFILTER, IDC_RICHEDIT_NOTES, OnEnMsgfilterRicheditNotes)
   ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify)
   ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify)
   
   ON_CBN_SELCHANGE(IDC_COMBO_NOTES_BOOK, &CNotesPage::OnSelectBibleBook)
   ON_CBN_SELCHANGE(IDC_COMBO_NOTES_CHAPTER, &CNotesPage::OnSelectBibleChapter)
   ON_CBN_SELCHANGE(IDC_FONTNAME, &CNotesPage::OnSelectFontName)
   ON_CBN_SELCHANGE(IDC_FONTSIZE, &CNotesPage::OnSelectFontSize)
 
   ON_NOTIFY(EN_LINK, IDC_RICHEDIT_NOTES, &CNotesPage::OnEnLinkRicheditNotes)
END_MESSAGE_MAP()


// CNotesPage message handlers

BOOL CNotesPage::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	
	IsPersonal = TRUE ;   // start by assuming that the personal database file exists
	
	// TODO: Add extra initialization here

	 if (!m_wndFormatBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD
       | WS_VISIBLE | CBRS_TOP |  CBRS_FLYBY | CBRS_TOOLTIPS) ||
       !m_wndFormatBar.LoadToolBar(IDR_NOTES_TOOLBAR))
   {
      TRACE0("Failed to create toolbar\n");
      return -1;      // fail to create
   }

	m_wndFormatBar.LoadTCToolBar(24, IDB_TOOLBAR_NOTES,IDB_TOOLBAR_NOTES,
                              IDB_TOOLBAR_NOTES, RGB(255,255,255));


	// Position the control bars using RepositionBars. 
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

	// Expand the size of the Toolbar window so all controls in it would fit
	

	// Expand the size of the Toolbar window so all controls in it would fit	
	CRect toolBarRect;
	CToolBarCtrl& formatBar = m_wndFormatBar.GetToolBarCtrl();
	formatBar.GetWindowRect(toolBarRect);
	ScreenToClient(toolBarRect);
	toolBarRect.right += 600 ;
	formatBar.MoveWindow(toolBarRect,TRUE);

	FillComboBoxes();

	////////////////////////////////// DATABASE STUFF //////////////////////////////////////////////////


	GetAppDirectory(path);
	path += _T("\\personal.mdb");

	 // Initialize the Recordset and binding pointers
     m_pRs = NULL;
     m_piAdoRecordBinding = NULL;


	 // Initialize the COM environment
     ::CoInitialize(NULL);
	 
   
	TCHAR * pChar = new TCHAR[400];
	memset(pChar, 0, 400);
	_stprintf(pChar, _T("Provider='Microsoft.JET.OLEDB.4.0';Data source = %s"),path);
	 m_strConnection = pChar;
    delete [] pChar;

		
    // if file DNE then create it
	if(GetFileAttributes(path) == -1)   // personal.mdb not there
	CreateDatabaseX(); 	// has the file been created successfully ? Check in the next step
	


	if(GetFileAttributes(path) == -1)
	 IsPersonal = FALSE;



	 CreateDB();



	
	 try {

	// Create the record set object
     m_pRs.CreateInstance(__uuidof(Recordset));

	 // set the command
	  m_strCmdText = _T("select * from PersonalTable");

	 // Open the record set object
     m_pRs->Open((LPCTSTR)m_strCmdText, (LPCTSTR)m_strConnection, 
            adOpenDynamic, adLockOptimistic, adCmdTableDirect);

	

	 // Get a pointer to the record binding interface
         if (FAILED(m_pRs->QueryInterface(__uuidof(IADORecordBinding),
                 (LPVOID *)&m_piAdoRecordBinding)))
             _com_issue_error(E_NOINTERFACE);


		  // Bind the record class to the record set
        m_piAdoRecordBinding->BindToRecordset(&m_rsRecSet);



		RefreshBoundData();

		
		 // if there are zero records, add a record
		if (m_pRs->BOF && m_pRs->EndOfFile)
		{
			
			m_pRs->AddNew();
			m_pRs->Fields->GetItem(long(0))->PutValue(_T("NULL")); 
			m_pRs->Fields->GetItem(long(1))->PutValue(_T("NULL")); 
			m_pRs->Update();
		}

	
	 CString curNotesChapter;
	 curNotesChapter.Format(_T("%d"),CSwordBibleDoc::curNotesChapter);
	 LoadEnteringID(CSwordBibleDoc::curNotesBook + curNotesChapter);
	
	
     }
     // Any errors?
     catch (_com_error &e)
     {
         // Display the error
         GenerateError(e.Error(), e.Description());
     }


	// to receive the mouse click events
	m_notesCtrl.SetEventMask(ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_SCROLLEVENTS|ENM_LINK);
	m_notesCtrl.SendMessage(EM_EXLIMITTEXT,0,-1);


	// set the format for the text in the notes box
	
	cf_default.dwMask = CFM_FACE|CFM_SIZE;
	_tcscpy(cf_default.szFaceName, _T("Arial"));
	cf_default.yHeight = 280;
	m_notesCtrl.SetDefaultCharFormat(cf_default);

	return FALSE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}


void CNotesPage::FillComboBoxes()
{
	/* Fill in the names of the Bible book in the Bible book combo */
	for( int i = 0; i < 66; i++)
	m_cmbBibleBook.AddString(CSwordBibleDoc::bookCode[i][0]);

	// set the selection to the current book
	int set_sel = m_cmbBibleBook.FindString(-1,CSwordBibleDoc::curNotesBook);
	m_cmbBibleBook.SetCurSel(set_sel);


	//find the # of chapters in the currently selected book and fill the combo box
	 oldCount =  _tstoi( CSwordBibleDoc::bookCode[m_cmbBibleBook.GetCurSel()][2] );
	 CString number;
	 for(int i = 0; i < oldCount; i++) {
		 number.Format(_T("%d"),i+1);			 
		 m_cmbBibleChapter.AddString(number);
	 }

	// set the chapter in the notes combo box
	 m_cmbBibleChapter.SetCurSel(CSwordBibleDoc::curNotesChapter - 1);	
	 m_cmbBibleChapter.LimitText(2);
	 
	
	 //////////////////////////////////////////////////////////////////////////


	m_cmbFontSize.LimitText(3);


	// Fill the Font names in the Font Name combo
    CClientDC dc(this);
	::EnumFontFamilies( dc.m_hDC, NULL, (FONTENUMPROC)EnumFontFamProc, 
				(LPARAM) this );

	// Fill the Font Size combo
	CString sSize;
	int nSizeCount = sizeof(nFontSizes) / sizeof(nFontSizes[0]);
	for(int j=0; j < nSizeCount; j++ )
	{
		sSize.Format(_T("%d"), nFontSizes[j] );
		m_cmbFontSize.AddString( sSize );
	}

	m_cmbFontName.SetCurSel(0);
	OnSelectFontName();
	m_cmbFontSize.SetCurSel(0);

}


void CNotesPage::OnSize(UINT nType, int cx, int cy)
{
	CPropertyPage::OnSize(nType, cx, cy);
	CWnd* pWnd = GetDlgItem(IDC_RICHEDIT_NOTES);

	// size the rich edit control
	if( ::IsWindow(pWnd ->GetSafeHwnd() )) 
	pWnd ->SetWindowPos(NULL,10,40,cx-20,cy-50,SWP_NOZORDER | SWP_NOACTIVATE);

	// size the bible book and chapter combo box
	if( ::IsWindow(m_cmbBibleBook.GetSafeHwnd() ))
	m_cmbBibleBook.SetWindowPos(NULL, 10, 8, 130,200,  SWP_NOZORDER | SWP_NOACTIVATE);

	if( ::IsWindow(m_cmbBibleChapter.GetSafeHwnd() ))
		m_cmbBibleChapter.SetWindowPos(NULL, 150, 8, 40, 200,  SWP_NOZORDER | SWP_NOACTIVATE);

	// size the font name and font size combo boxes
	if( ::IsWindow(m_cmbFontName.GetSafeHwnd() ))
	 m_cmbFontName.SetWindowPos(NULL, 458, 8, 170,200, SWP_NOZORDER | SWP_NOACTIVATE);

	if( ::IsWindow(m_cmbFontSize.GetSafeHwnd() ))
		m_cmbFontSize.SetWindowPos(NULL, 635, 8, 40, 200,  SWP_NOZORDER | SWP_NOACTIVATE);



}
void CNotesPage::OnCharColor() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	m_notesCtrl.SelectColor();

}



void CNotesPage::OnCharItalic() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;
	

	m_notesCtrl.SetSelectionItalic();
	
	
}

void CNotesPage::OnUpdateCharItalic(CCmdUI* pCmdUI) 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	CSwordBibleDoc::notesItalic = m_notesCtrl.SelectionIsItalic();

	if( CSwordBibleDoc::notesItalic == TRUE)
	pCmdUI ->SetCheck(1);

	else pCmdUI ->SetCheck(0);
	
}

void CNotesPage::OnCharUnderline() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	m_notesCtrl.SetSelectionUnderlined();
	
	
}

void CNotesPage::OnUpdateCharUnderline(CCmdUI* pCmdUI) 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	CSwordBibleDoc::notesUnderline = m_notesCtrl.SelectionIsUnderlined();

	if( CSwordBibleDoc::notesUnderline == TRUE)
	pCmdUI ->SetCheck(1);

	else pCmdUI ->SetCheck(0);
	
	
}

void CNotesPage::OnInsertBullet() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	m_notesCtrl.SetParagraphBulleted();
	
}

void CNotesPage::OnUpdateInsertBullet(CCmdUI* pCmdUI) 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	pCmdUI = NULL;
}

void CNotesPage::OnParaCenter() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	m_notesCtrl.SetParagraphCenter();
	
}

void CNotesPage::OnUpdateParaCenter(CCmdUI* pCmdUI) 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	CSwordBibleDoc::notesParaCenter = m_notesCtrl.ParagraphIsCentered();
	pCmdUI->SetCheck(CSwordBibleDoc::notesParaCenter);
		

	
}

void CNotesPage::OnParaLeft() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	m_notesCtrl.SetParagraphLeft();
}

void CNotesPage::OnUpdateParaLeft(CCmdUI* pCmdUI) 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	CSwordBibleDoc::notesParaLeft = m_notesCtrl.ParagraphIsLeft();
	pCmdUI->SetCheck(CSwordBibleDoc::notesParaLeft);

}

void CNotesPage::OnParaRight() 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	m_notesCtrl.SetParagraphRight();	
}

void CNotesPage::OnUpdateParaRight(CCmdUI* pCmdUI) 
{
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	CSwordBibleDoc::notesParaRight = m_notesCtrl.ParagraphIsRight();
	pCmdUI->SetCheck(CSwordBibleDoc::notesParaRight);

		
}

void CNotesPage::OnCharBold() 
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	m_notesCtrl.SetSelectionBold();
}

void CNotesPage::OnUpdateCharBold(CCmdUI* pCmdUI) 
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	CSwordBibleDoc::notesBold = m_notesCtrl.SelectionIsBold();
	if(CSwordBibleDoc::notesBold == TRUE)
	pCmdUI ->SetCheck(1);

	else pCmdUI ->SetCheck(0);
	
	
}

void CNotesPage::OnRtfCopy() 
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	// TODO: Add your command handler code here
		m_notesCtrl.Copy();
	
}

void CNotesPage::OnRtfCut() 
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	// TODO: Add your command handler code here
	m_notesCtrl.Cut();
}



void CNotesPage::OnRtfPaste() 
{


	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
		  ((CPropertySheet*) GetParent())->SetActivePage(this);
	  
	
	
	// TODO: Add your command handler code here
	m_notesCtrl.Paste();
	
}

void CNotesPage::OnRtfSave() 
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;


	// TODO: Add your command handler code here
		if(IsPersonal == FALSE)
		return ;    // no point in continuing if database DNE

	CString chapStr;
	chapStr.Format(_T("%d") , CSwordBibleDoc::curNotesChapter);

	CString ID = CSwordBibleDoc::curNotesBook + chapStr;



	try {
		// Update the current record
		if(m_piAdoRecordBinding)
      m_piAdoRecordBinding->Update(&m_rsRecSet);

	if (m_pRs->BOF == FALSE)
	 m_pRs->MoveFirst();


	//_variant_t tofind(ID);
    // m_pRs->Seek(tofind, adSeekFirstEQ );
	CString tofind;
	tofind.Format(_T("Verse='%s'"), ID);
	m_pRs->Find(tofind.AllocSysString() , 0, ADOCG::adSearchForward);  
	RefreshBoundData();

	if( verse_code == ID) 
	{
		data = m_notesCtrl.GetRTF();
		UpdateBoundData();	
		m_piAdoRecordBinding->Update(&m_rsRecSet);
		
	}


	// if the record is not there, lets add a new record
	else  {		

	AddNew();

	// lets copy the verse code and string into temp variable of THIS class
	verse_code = ID;
	data = m_notesCtrl.GetRTF();
	UpdateBoundData();
	m_piAdoRecordBinding->Update(&m_rsRecSet);
	
	}
	}
	   // Any errors?
 catch (_com_error &e) {         // Generate an error message
         GenerateError(e.Error(), e.Description());
 }
}

void CNotesPage::OnNotesPrint()
{
			// only the active page should handle the message
	if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	CBibleForm::pControl = (CRichEditCtrl *) GetDlgItem(IDC_RICHEDIT_NOTES);
	AfxGetMainWnd()->SendMessageToDescendants(WM_PRINT_CONTROL, (WPARAM) 1 , 0);

}



LONG CNotesPage::OnBarReturn(UINT , LONG )
{	m_notesCtrl.SetFocus();
	return 0;
}

void CNotesPage::OnInsertLink()
{

 if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
		  ((CPropertySheet*) GetParent())->SetActivePage(this);

  CVersePicker dlg;  //open a dialog from which user can select a verse key

  if(dlg.DoModal() == IDOK) {

  CHARFORMAT2 cf; 
  m_notesCtrl.GetSelectionCharFormat(cf);

  m_notesCtrl.SetSelectionLink();
  CString csInsert = _T("[") + dlg.key + _T("]");
  m_notesCtrl.ReplaceSel(csInsert);

  m_notesCtrl.SetSelectionCharFormat(cf);
  }


}

LONG CNotesPage::OnMainFrameCommand(UINT, LONG)
{

	 if (ActiveMainFrameCommand == _T("previous"))			OnPrevious();
	 else if(ActiveMainFrameCommand == _T("BibleSynch"))    BibleSynch(); // synchronize notes with current bible book/chapter
   else if(ActiveMainFrameCommand == _T("insertlink"))  OnInsertLink();	
   else if (ActiveMainFrameCommand == _T("next"))         OnNext();
	 else if (ActiveMainFrameCommand == _T("save"))			OnRtfSave();
	 else if (ActiveMainFrameCommand == _T("print"))		OnNotesPrint();
	 else if (ActiveMainFrameCommand == _T("synchronize"))  OnSynch();
	 else if (ActiveMainFrameCommand == _T("cut"))		OnRtfCut();
	 else if (ActiveMainFrameCommand == _T("copy"))			OnRtfCopy();
	 else if (ActiveMainFrameCommand == _T("paste"))		OnRtfPaste();
	 else if (ActiveMainFrameCommand == _T("bold"))			OnCharBold();
     else if (ActiveMainFrameCommand == _T("italic"))		OnCharItalic();
	 else if (ActiveMainFrameCommand == _T("underline"))    OnCharUnderline();
	 else if (ActiveMainFrameCommand == _T("left"))			OnParaLeft();
	 else if (ActiveMainFrameCommand == _T("center"))		OnParaCenter();
     else if (ActiveMainFrameCommand == _T("right"))		OnParaRight();
	 else if (ActiveMainFrameCommand == _T("bullets"))	OnInsertBullet();
	
		return 0L;
}



LONG CNotesPage::OnChangeNotesChapter(UINT , LONG lp)
{
	m_notesCtrl.SetWindowText(_T(""));

	if(IsPersonal == FALSE)
		return 0L;    // no point in continuing if database DNE

	try {


	// Now that we have saved the leaving chapter, lets load up the text for 
	// the new chapter

	CString curNotesChapter;
	curNotesChapter.Format(_T("%d"),CSwordBibleDoc::curNotesChapter);
	
	CString newID = CSwordBibleDoc::curNotesBook +  curNotesChapter;

	LoadEnteringID(newID);

	
	}

	   // Any errors?
     catch (_com_error &e)
     {
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }


		
		return 0L;
}




LONG CNotesPage::OnChangeNotesBook(UINT , LONG lp)
{

	m_notesCtrl.SetWindowText(_T(""));

	if(IsPersonal == FALSE)
		return 0L;    // no point in continuing if database DNE


	try{

	

	// lets load up the text for the new chapter
	CString newID = CSwordBibleDoc::curNotesBook +  _T("1");//notesChapName;

	LoadEnteringID(newID);	
	}



	 catch (_com_error &e)
     {
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }

	
		return 0L;
}



bool CNotesPage::GetAppDirectory( CString& strAppDir )
{
   bool bRet        = false;
   DWORD dwSize     = _MAX_PATH + 1;
   LPTSTR pszAppDir = new TCHAR[dwSize];

   if( ::GetModuleFileName( NULL, pszAppDir, dwSize ) )
   {
      strAppDir = pszAppDir;
      int nPos = 0; 
	  nPos = strAppDir.ReverseFind(_T('\\'));
      if( -1 != nPos )
      {
         strAppDir = strAppDir.Left( nPos );
         bRet = true;
      }
   }
   delete []pszAppDir;

   return bRet;

}

void CNotesPage::OnSynch() 
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	// TODO: Add your command handler code here
	CSwordBibleDoc::notesSynch  =  !(CSwordBibleDoc::notesSynch);

	// write synchronization settings to the registry
	AfxGetApp()->WriteProfileInt(_T("Notes"),_T("Synchronize"),CSwordBibleDoc::notesSynch);

	if(CSwordBibleDoc::notesSynch)
		BibleSynch();
	
}

void CNotesPage::OnUpdateSynch(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if(CSwordBibleDoc::notesSynch == TRUE)
		pCmdUI->SetCheck(1);

	else if (CSwordBibleDoc::notesSynch == FALSE)
		pCmdUI->SetCheck(0);
	
}


void CNotesPage::BibleSynch()
{
	// only the active page should handle the message
	  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	int Book = CSwordBibleDoc::Book()  - 1;
	int Chapter = CSwordBibleDoc::Chapter() - 1;

	m_cmbBibleBook.SetCurSel(Book);
	OnSelectBibleBook();

	m_cmbBibleChapter.SetCurSel(Chapter);
	OnSelectBibleChapter();

}

void CNotesPage::RefreshBoundData()
{
	if(IsPersonal == FALSE)
	return;    // no point in continuing if database DNE
	
	try {

		if (adFldOK == m_rsRecSet.lVerseCodeStatus)
         // Copy the value
        verse_code = m_rsRecSet.m_szVerseCode;
     else
         // Otherwise, set the value to 0
         verse_code = _T("");


	 	if (adFldOK == m_rsRecSet.lVerseTextStatus)
         // Copy the value
         data.Format(_T("%s"), m_rsRecSet.m_szVerseText);
     else
         // Otherwise, set the value to 0
         data.Format(_T("%s"), _T("") );

	}

	   // Any errors?
     catch (_com_error &e)
     {
		
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }

}




void CNotesPage::OnDestroy() 
{
	CPropertyPage::OnDestroy();

	if(IsPersonal == FALSE)
		return ;    // no point in continuing if database DNE

  FILE* h_file = _tfopen(path, _T("r"));
	fseek(h_file, 0, SEEK_END);
	long size = ftell(h_file);
	fclose(h_file);

	if(size > 15728640) CompactDatabase();    // > 15 MB?

	
}



void CNotesPage::GenerateError(HRESULT hr, PWSTR pwszDescription)
{

    CString strError;

     // Format and display the error message
     strError.Format(_T("Run-time error `%d (%x)'"), hr, hr);
     strError += _T("\n\n");
     strError += pwszDescription;

     AfxMessageBox(strError);


}

void CNotesPage::UpdateBoundData()
{

	if(IsPersonal == FALSE)
		return ;    // no point in continuing if database DNE

	try {

	if ( _tcscmp(verse_code, m_rsRecSet.m_szVerseCode) != 0 )
      _tcscpy(m_rsRecSet.m_szVerseCode, verse_code);

	if ( _tcscmp(data , m_rsRecSet.m_szVerseText)   != 0      )
      _tcscpy(m_rsRecSet.m_szVerseText,data);

	}

	   // Any errors?
     catch (_com_error &e)
     {
		
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }

}



void CNotesPage::AddNew()
{
	if(IsPersonal == FALSE)
		return ;    // no point in continuing if database DNE

	try
     {
		  
         // Update the current record
         m_piAdoRecordBinding->Update(&m_rsRecSet);
         // Can we add a new record?
         if (m_pRs->Supports(adAddNew))
         {
             // Create a blank record
             CreateBlankRecord();
			
             // Add the blank record
             m_piAdoRecordBinding->AddNew(&m_rsRecSet);
             // Move to the last record
			 if(m_pRs->EndOfFile == FALSE)
            m_pRs->MoveLast();
         }
     }
     // Any errors?
     catch (_com_error &e)
     {
         // Generate an error message
		
         GenerateError(e.Error(), e.Description());
     }

}



void CNotesPage::CreateBlankRecord()
{
	if(IsPersonal == FALSE)
		return;    // no point in continuing if database DNE

	try {

    // Create the blank values to be used
     CString strBlank = _T("");
	

	_tcscpy(m_rsRecSet.m_szVerseCode, strBlank);
   _tcscpy(m_rsRecSet.m_szVerseText, strBlank);
	 
	}

	   // Any errors?
     catch (_com_error &e)
     {
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }



}

void CNotesPage::Delete()
{
	if(IsPersonal == FALSE)
		return ;    // no point in continuing if database DNE

     try
     {
         // Update the current record
         m_piAdoRecordBinding->Update(&m_rsRecSet);
         // Can we delete a record?
         if (m_pRs->Supports(adDelete))
         {
             
                 // Delete the record
                 m_pRs->Delete(adAffectCurrent);
                 // Move to the previous record
                 m_pRs->MovePrevious();
            
         }



     }
     // Any errors?
     catch (_com_error &e)
     {
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }

}



void CNotesPage::LoadEnteringID(CString ID)
{
	m_notesCtrl.SetWindowText(_T("")); //clear the notes window text

	m_notesCtrl.SetDefaultCharFormat(cf_default);


	if(IsPersonal == FALSE)
		return ;    // no point in continuing if database DNE

	try
	{

	if (m_pRs->BOF == FALSE)
	 m_pRs->MoveFirst();

	
	CString tofind;
	tofind.Format(_T("Verse='%s'"), ID);
	m_pRs->Find(tofind.AllocSysString() , 0, ADOCG::adSearchForward);  
	RefreshBoundData();

	if( verse_code == ID)  m_notesCtrl.SetRTF(data);

  RecreateNoteLinks();
	
	}

	   // Any errors?
     catch (_com_error &e)
     {
		 
         // Generate an error message
         GenerateError(e.Error(), e.Description());

	 }

}


void CNotesPage::RecreateNoteLinks()
{
  FINDTEXTEX ft1, ft2;
	ft1.chrg.cpMin = 0;
	ft1.chrg.cpMax = -1;
	ft1.lpstrText = _T("[");

	ft2.chrg.cpMin = 0;
	ft2.chrg.cpMax = -1;
	ft2.lpstrText = _T("]");

	int start = 0, end = 0;

	while (true) {	
	start = m_notesCtrl.FindText(FR_DOWN , &ft1); //find the href start tags  
	end = m_notesCtrl.FindText(FR_DOWN , &ft2); //find the href tags  

	if(start == -1 || end == -1 || start > end)   {
    m_notesCtrl.SetSel(-1,0);		// position the caret correctly
    return;
  }

	CString ref = _T("");
	m_notesCtrl.GetTextRange(start + 1, end, ref);
	
  if(ref.Find(_T(':')) != -1) {
    m_notesCtrl.SetSel(start + 1, end);
    m_notesCtrl.SetSelectionLink();
  }

	ft1.chrg.cpMin = start + 1;
	ft2.chrg.cpMin = end + 1;
	}



}


BOOL CNotesPage:: CreateDB() 

{
	// programmatically configure a user's machine to use access database

	TCHAR* szDesc;
	int mlen;
	szDesc = new TCHAR[256];

	CString csPath = path;

	_stprintf(szDesc,_T("DSN=%s; DESCRIPTION=%s; DBQ=%s; FIL=MicrosoftAccess; DEFAULTDIR=%s"),  _T("SwordBibleDSN"), _T(""),
	csPath	, _T(""));
	mlen = _tcsclen(szDesc);
	for (int i = 0; i < mlen; i++)
	{
		if (szDesc[i] == _T(';'))
			szDesc[i] = _T('\0');
	}
	
	BOOL bOk = SQLConfigDataSource(NULL, ODBC_ADD_DSN, _T("Microsoft Access Driver (*.mdb)\0"), (LPCTSTR)szDesc);
	if(!bOk)
		::AfxMessageBox(_T("Failed"), MB_OK);

	delete [] szDesc;
	return bOk;



	
	
}

//------------------------------------------------------------//
//CreateDatabaseX                                
//Purpose:  create a new Jet database with the Create method
//------------------------------------------------------------//
void CNotesPage::CreateDatabaseX()
{    
    HRESULT hr = S_OK;

    // Define ADOX object pointers.
    // Initialize pointers on define.
    // These are in the ADOX::  namespace.
    
ADOX::_CatalogPtr m_pCatalog = NULL;
ADOX::_TablePtr m_pTable = NULL;


    try
    {//Open the catalog


		TESTHR(hr = m_pCatalog.CreateInstance(__uuidof(ADOX::Catalog)));
		m_pCatalog->Create(m_strConnection.AllocSysString() );
	

		// add the tables to the file
		TESTHR(m_pTable.CreateInstance(__uuidof(ADOX::Table)));
		m_pTable->PutName(_T("PersonalTable"));
		m_pTable->Columns->Append(_T("Verse"),ADOX::adVarWChar,50);
		m_pTable->Columns->Append(_T("Text"),ADOX::adLongVarWChar,65000);

		m_pCatalog->Tables->Append(
		_variant_t((IDispatch *)m_pTable));

		
		m_pCatalog->Tables->Refresh();

	m_strCmdText = _T("CREATE UNIQUE INDEX IDX_VERSE on PersonalTable (Verse)");
		ADOCG::_ConnectionPtr con = m_pCatalog->GetActiveConnection();
		con->Execute(m_strCmdText.AllocSysString() , NULL, adExecuteNoRecords);
				


m_pCatalog = NULL;

    }
    catch(_com_error &e)
    {
        // Notify the user of errors if any.
        _bstr_t bstrSource(e.Source());
        _bstr_t bstrDescription(e.Description());
          
        _tprintf(_T("\n\tSource :  %s \n\tdescription : %s \n "),
            (LPCTSTR)bstrSource,(LPCSTR)bstrDescription);

    }
    catch(...)
    {
        AfxMessageBox(_T("Error occured in CreateDatabaseX...."));
    }

}

void CNotesPage::CompactDatabase()
{
	CString filename = path;

	CDaoDatabase db;
	
	CString tempFile = filename;
	tempFile.Replace(_T("personal.mdb"),_T("personalTemp.mdb"));
	
    // close the database
	try {	

	if (m_pRs)
	{
		if(m_pRs->State == adStateOpen)		m_pRs->Close();				
		m_pRs.Release();
		m_pRs = NULL;
	
	}
	
	if(m_piAdoRecordBinding)
	 {
		m_piAdoRecordBinding->Release();
		 m_piAdoRecordBinding = NULL;

	}


	 ::CoUninitialize();

	}

 // Any errors?
     catch (_com_error &e)
     {
         // Display the error
         GenerateError(e.Error(), e.Description());
     }

	
    // compact the database
	try
	{
	

	db.m_pWorkspace->CompactDatabase(filename, tempFile , dbLangGeneral);
	CFile::Remove(filename);

	db.m_pWorkspace->CompactDatabase(tempFile,filename , dbLangGeneral);
	CFile::Remove(tempFile); // delete the data temp file


	}
	catch (CDaoException *e)
	{
	AfxMessageBox (e->m_pErrorInfo->m_strDescription);
	e->Delete();
	}

}




void CNotesPage::OnEnMsgfilterRicheditNotes(NMHDR *pNMHDR, LRESULT *pResult)
{
	MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
	// TODO:  The control will not send this notification unless you override the
	// CPropertyPage::OnInitDialog() function to send the EM_SETEVENTMASK message
	// to the control with either the ENM_KEYEVENTS or ENM_MOUSEEVENTS flag 
	// ORed into the lParam mask.

	// TODO:  Add your control notification handler code here

 	if(pMsgFilter->msg == WM_MOUSEMOVE) return; // don't need mouse move messages right now

 
	OnUpdateRichEdit();
	
	if (pMsgFilter->msg == WM_RBUTTONDOWN)        {
     
      
     CPoint point;                                            
     ::GetCursorPos(&point); //where is the mouse?
     CMenu menu; //lets display out context menu :) 
     DWORD dwSelectionMade;                                       
     VERIFY(menu.LoadMenu(IDR_MENU_NOTESPAGE) );  
    CMenu *pmenuPopup = menu.GetSubMenu(0);
     ASSERT(pmenuPopup != NULL);       


	  if(CSwordBibleDoc::notesSynch)		pmenuPopup->CheckMenuItem(ID_NOTES_SYNCHRONIZE,MF_CHECKED); 
	  if(CSwordBibleDoc::notesBold)			pmenuPopup->CheckMenuItem(ID_NOTES_BOLD,MF_CHECKED); 
	  if(CSwordBibleDoc::notesItalic)		pmenuPopup->CheckMenuItem(ID_NOTES_ITALIC,MF_CHECKED); 
	  if(CSwordBibleDoc::notesUnderline)	pmenuPopup->CheckMenuItem(ID_NOTES_UNDERLINE,MF_CHECKED); 
	  if(CSwordBibleDoc::notesParaLeft)     pmenuPopup->CheckMenuItem(ID_NOTES_LEFTALIGN,MF_CHECKED); 
	  if(CSwordBibleDoc::notesParaCenter)   pmenuPopup->CheckMenuItem(ID_NOTES_CENTERALIGN,MF_CHECKED); 
	  if(CSwordBibleDoc::notesParaRight)    pmenuPopup->CheckMenuItem(ID_NOTES_RIGHTALIGN,MF_CHECKED); 


    dwSelectionMade = pmenuPopup->TrackPopupMenu( (TPM_LEFTALIGN|TPM_LEFTBUTTON|
                                                      TPM_RETURNCMD),
                                                    point.x, point.y, this); 

	switch(dwSelectionMade)
	{

	case ID_NOTES_PREVIOUSCHAPTER:						OnPrevious();		  break;
	case ID_NOTES_NEXTCHAPTER:							OnNext();			  break;
	case ID_NOTES_SAVE:									OnRtfSave();		  break;
	case ID_NOTES_PRINT:								OnNotesPrint();		  break;
	case ID_NOTES_SYNCHRONIZE:							OnSynch();			  break;
	case ID_NOTES_CUT:									OnRtfCut();			  break;
	case ID_NOTES_COPY:									OnRtfCopy();		  break;
	case ID_NOTES_PASTE:								OnRtfPaste();		  break;
	case ID_NOTES_BOLD:									OnCharBold();		  break;
    case ID_NOTES_ITALIC:								OnCharItalic();		  break;
	case ID_NOTES_UNDERLINE:							OnCharUnderline();    break;
	case ID_NOTES_LEFTALIGN:							OnParaLeft();         break;
	case ID_NOTES_CENTERALIGN:							OnParaCenter();       break;
    case ID_NOTES_RIGHTALIGN:							OnParaRight();        break;
	case ID_NOTES_INSERTBULLETS:						OnInsertBullet();     break;

	}
     
     pmenuPopup->DestroyMenu(); 
  
               
    }

	*pResult = 0;
}



BOOL CNotesPage::OnToolTipNotify(UINT id, NMHDR *pNMHDR,   LRESULT *pResult)
{
   ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);

     // if there is a top level routing frame then let it handle the message
     if (GetRoutingFrame() != NULL) return FALSE;

     // to be thorough we will need to handle UNICODE versions of the message also !!
     TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
     TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
     TCHAR szFullText[512];
     CString strTipText;
     UINT nID = pNMHDR->idFrom;

     if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
         pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
     {
          // idFrom is actually the HWND of the tool 
          nID = ::GetDlgCtrlID((HWND)nID);
     }

     if (nID != 0) // will be zero on a separator
     {
          AfxLoadString(nID, szFullText);
          strTipText=szFullText;

#ifndef _UNICODE
          if (pNMHDR->code == TTN_NEEDTEXTA)
          {
               lstrcpyn(pTTTA->szText, strTipText, sizeof(pTTTA->szText));
          }
          else
          {
               _mbstowcsz(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
          }
#else
          if (pNMHDR->code == TTN_NEEDTEXTA)
          {
               _wcstombsz(pTTTA->szText, strTipText,sizeof(pTTTA->szText));
          }
          else
          {
               lstrcpyn(pTTTW->szText, strTipText, sizeof(pTTTW->szText));
          }
#endif

          *pResult = 0;

          // bring the tooltip window above other popup windows
          ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,SWP_NOACTIVATE|
               SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); return TRUE;
     }

     return FALSE;
}



void CNotesPage::OnSelectBibleBook()
{
	
   // since the user has selected a new book, the current book will become oldBook
	CString oldBook = CSwordBibleDoc::curNotesBook;

	// the 0 based index of the new book that the user has selected
	int selectedBook  = m_cmbBibleBook.GetCurSel();

	// change the active bible book for the notes section
	CSwordBibleDoc::curNotesBook = CSwordBibleDoc::bookCode[selectedBook][0];
	        

	// empty the strings in the chapter combo box of the notes
	for(int ni = 0; ni < oldCount ; ni++)
	m_cmbBibleChapter.DeleteString(0);


    // get the total number of chapters in the newly selected book
	int totalChap =_tstoi(CSwordBibleDoc::bookCode[selectedBook][2]);


   // add the "chapter number" strings in the chapter combo box of the notes
	CString indexString;
	for(int nni = 0; nni < totalChap ; nni++)  // nni = new notes index
	{ 
		indexString.Format(_T("%d"),nni + 1);
		m_cmbBibleChapter.AddString(indexString);
	}

	m_cmbBibleChapter.SetCurSel(0);

	
   // set the oldCount to the number of chapters in the current book of the bible in the 
	// notes section. This variable is used later during the deletion of the strings.
	oldCount = totalChap;

	// change the record in the document class
	CSwordBibleDoc::curNotesChapter = 1; // not a zero based index
	
	OnChangeNotesBook(0, 0);


}

void CNotesPage::OnSelectBibleChapter()
{
		 // since the user has selected a new chapter in the notes, the current chapter
	// will become oldChapter
	int oldChapter = CSwordBibleDoc::curNotesChapter;

	// the newly selected chapter from the notes combo box
	int selectedChapter  = m_cmbBibleChapter.GetCurSel();

	// change the record in the document class
	CSwordBibleDoc::curNotesChapter = selectedChapter + 1; // not a zero based index

	OnChangeNotesChapter(0, oldChapter);
}


// This function is called when a user selects new font name using combo box
void CNotesPage::OnSelectFontName()
{
	TCHAR szFontName[LF_FACESIZE];
	int nIndex = m_cmbFontName.GetCurSel();
	m_cmbFontName.GetLBText( nIndex, szFontName );

	// If font name is empty - return
	if( szFontName[0] == 0 )
		return;

  cf_default = m_notesCtrl.GetCharFormat();

	cf_default.dwMask |= CFM_FACE;

	_tcsncpy(cf_default.szFaceName, szFontName, LF_FACESIZE);	//strncpy


	long start=0, end=0;
	m_notesCtrl.GetSel(start, end);         // get currently selected text

	if(start == end)
	{
		start--;
		m_notesCtrl.SetSel(start, end);  
	}
		
    	
	m_notesCtrl.SetSelectionCharFormat(cf_default);
 
	m_notesCtrl.SetFocus();
	m_notesCtrl.SetSel(end,end);		// position the caret correctly


}


// This function is called when a user selects new font size using combo box
void CNotesPage::OnSelectFontSize()
{
	TCHAR szSize[5];
	int index = m_cmbFontSize.GetCurSel();
	if( index != CB_ERR )
		m_cmbFontSize.GetLBText(index, szSize );
	else
		m_cmbFontSize.GetWindowText( szSize, 5 );

	// Get size in Twips
	int nSize =_tstoi( szSize ) * 20;			// atoi for tchar

	if( !nSize )
		return;

  cf_default = m_notesCtrl.GetCharFormat();
	
  cf_default.dwMask |= CFM_SIZE;
	cf_default.yHeight = nSize;

   	long start=0, end=0;
	m_notesCtrl.GetSel(start, end);         // get currently selected text

	if(start == end)
	{
		start--;
		m_notesCtrl.SetSel(start, end);  
	}
		
    	
	m_notesCtrl.SetSelectionCharFormat(cf_default);

	m_notesCtrl.SetFocus();
	m_notesCtrl.SetSel(end,end);		// position the caret correctly

}


void CNotesPage::OnUpdateRichEdit()
{
		// Don't update the combo boxes if user changing font attribute or the 
	    // Bible chapter attribute
	
	CWnd *pWnd = GetFocus();
	if(pWnd != &m_notesCtrl) return;

	
	// get the current font from the view and update
	cf_default = m_notesCtrl.GetCharFormat();



	// Update the font only if the selection font is different
	TCHAR szName[LF_FACESIZE];
	m_cmbFontName.GetWindowText( szName, LF_FACESIZE );

	// the selection must be same font and charset to display correctly
	if ((cf_default.dwMask & (CFM_FACE|CFM_CHARSET)) != (CFM_FACE|CFM_CHARSET))
		m_cmbFontName.SetCurSel( -1 );
	else if( ::_tcscmp( szName, cf_default.szFaceName ) != 0 )
	{
		if( m_cmbFontName.SelectString( -1, cf_default.szFaceName ) == CB_ERR )
			m_cmbFontName.SetCurSel( -1 );
	}


	// Update the font size
	TCHAR szSize[5];
	m_cmbFontSize.GetWindowText( szSize, 5 );
	int nSize = _tstoi( szSize );				// atoi for tchar

	// Update the font size only if selection is different 
	int nSelSize = (cf_default.dwMask & CFM_SIZE) ? cf_default.yHeight/20 : 0;
	if( nSize != nSelSize )
	{
		if(cf_default.dwMask & CFM_SIZE)
		{
			CString strSize;
			strSize.Format(_T("%d"), nSelSize );
			m_cmbFontSize.SelectString(-1,strSize);
				
		}
		else
			m_cmbFontSize.SetCurSel(-1);
	}
}



int CALLBACK CNotesPage::EnumFontFamProc(ENUMLOGFONT *lpelf, NEWTEXTMETRIC *,
					int , LPARAM lParam)
{
	CNotesPage* pWnd = (CNotesPage*)lParam;

	// Add the font name to the combo
	pWnd->m_cmbFontName.AddString(lpelf->elfLogFont.lfFaceName);

	return 1;		// 1 to continue enumeration
}

void CNotesPage::OnPrevious()
{

		// only the active page should handle the message
  if(     ((CPropertySheet*) GetParent())->GetActivePage()   != this) return;

    
 int curChap   = m_cmbBibleChapter.GetCurSel();   // zero based index

  if(curChap > 0)
  {
	  m_cmbBibleChapter.SetCurSel(curChap - 1);
	  OnSelectBibleChapter();
	  return;
  }

  int curBook = m_cmbBibleBook.GetCurSel();        // zero based index

  if(curBook > 0)
  {
 
	m_cmbBibleBook.SetCurSel(curBook - 1);         // jump to the previous chapter
	OnSelectBibleBook();
  }

  else return;

  // jump to the last chapter
   int totalChap = m_cmbBibleChapter.GetCount();
   m_cmbBibleChapter.SetCurSel(totalChap - 1);
   OnSelectBibleChapter();




}

void CNotesPage::OnNext()
{
	// only the active page should handle the message
  if(     ((CPropertySheet*) GetParent())->GetActivePage()   != this) return;



    
  int totalChap = m_cmbBibleChapter.GetCount();
  int curChap   = m_cmbBibleChapter.GetCurSel();   // zero based index

  if(curChap < totalChap - 1)
  {
	  m_cmbBibleChapter.SetCurSel(curChap + 1);
	  OnSelectBibleChapter();
	  return;
  }

  int totalBooks = m_cmbBibleBook.GetCount();
  int curBook = m_cmbBibleBook.GetCurSel();        // zero based index

  if(curBook < totalBooks - 1)
  {

	m_cmbBibleBook.SetCurSel(curBook + 1);
	OnSelectBibleBook();
  }
}


BOOL CNotesPage::OnSetActive()
{
	BOOL result = CPropertyPage::OnSetActive();


	if(CSwordBibleDoc::notesSynch) // synchronize notes with current bible book/chapter
	{
	m_cmbBibleBook.SetCurSel( CSwordBibleDoc::Book()  - 1 );
	OnSelectBibleBook();

	m_cmbBibleChapter.SetCurSel( CSwordBibleDoc::Chapter() - 1 );
	OnSelectBibleChapter();
	}

	return result;
}
void CNotesPage::OnEnLinkRicheditNotes(NMHDR *pNMHDR, LRESULT *pResult)
{
  ENLINK *pEnLink = reinterpret_cast<ENLINK *>(pNMHDR);

  if(pEnLink->msg == WM_LBUTTONDOWN)
  {
    int min = pEnLink->chrg.cpMin;
    int max = pEnLink->chrg.cpMax;
    m_notesCtrl.SetSel(min, max);
    CString csRefString = m_notesCtrl.GetSelText();

    CMainFrame * pWnd = (CMainFrame*) AfxGetMainWnd();

   pWnd->GoToBibleVerse(csRefString);

  }
  
  *pResult = 0;
}
